package com.punai.enterprisedatadisplay.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.punai.common.core.domain.entity.EcoCompany;
import com.punai.common.core.domain.entity.EcoCompanyDept;
import com.punai.common.core.domain.entity.SysUser;
import com.punai.common.utils.NumberUtil;
import com.punai.common.utils.SecurityUtils;
import com.punai.common.utils.ServletUtils;
import com.punai.enterprisedatadisplay.constanta.OvershootSituationConstanta;
import com.punai.enterprisedatadisplay.domain.vo.OvershootSituationVo;
import com.punai.enterprisedatadisplay.service.OvershootSituationService;
import com.punai.external.domain.bo.PmProjectInfoBO;
import com.punai.externalccb.domain.EcoCbfeeitem;
import com.punai.externalccb.mapper.EcoCbfeeitemMapper;
import com.punai.prodatalibrary.domain.LibProject;
import com.punai.prodatalibrary.mapper.LibProjectMapper;
import com.punai.system.mapper.EcoCompanyDeptMapper;
import com.punai.system.mapper.EcoCompanyMapper;
import com.punai.system.mapper.SysUserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@Transactional
public class OvershootSituationServiceImpl implements OvershootSituationService {
    @Autowired
    private LibProjectMapper libProjectMapper;
    @Autowired
    private EcoCompanyMapper ecoCompanyMapper;
    @Autowired
    private EcoCompanyDeptMapper ecoCompanyDeptMapper;
    @Autowired
    private SysUserMapper sysUserMapper;
    @Autowired
    private EcoCbfeeitemMapper cbfeeitemMapper;
    @Override
    public List<OvershootSituationVo> getTableData(OvershootSituationVo vo) throws ParseException {
        String tabVal = vo.getTabVal();
        Date startDate = null;
        Date endDate = vo.getSelDate();
        int year = DateUtil.year(endDate);
        int month = DateUtil.month(endDate) + 1;
        if (OvershootSituationConstanta.Tabs.DATA_DN.getCode().equals(tabVal)) {
            //当年
            startDate = new SimpleDateFormat("yyyy-MM-dd").parse(year +"-01-01");
        } else if (OvershootSituationConstanta.Tabs.DATA_DJ.getCode().equals(tabVal)) {
            //当季
            int quarter = DateUtil.quarter(endDate);
            if(quarter == 1) startDate = new SimpleDateFormat("yyyy-MM-dd").parse(year + "-01-01");
            if(quarter == 2) startDate = new SimpleDateFormat("yyyy-MM-dd").parse(year + "-04-01");
            if(quarter == 3) startDate = new SimpleDateFormat("yyyy-MM-dd").parse(year + "-07-01");
            if(quarter == 4) startDate = new SimpleDateFormat("yyyy-MM-dd").parse(year + "-10-01");
        } else if (OvershootSituationConstanta.Tabs.DATA_DY.getCode().equals(tabVal)) {
            //当月
            startDate = new SimpleDateFormat("yyyy-MM-dd").parse(year + "-"+ month+"-01");
        }

        //组装vo，将每一行的分公司和项目关联起来
        List<OvershootSituationVo> vos = this.assembleProjectToVo();

        //已关联，处理每一行分公司后续数据汇总
        for (OvershootSituationVo overshootSituationVo : vos) {
            List<LibProject> projects = overshootSituationVo.getProjects();
            BigDecimal htsr = new BigDecimal("0.00");
            BigDecimal mbcb = new BigDecimal("0.00");
            BigDecimal mbcb_tzh = new BigDecimal("0.00");
            for (LibProject project : projects) {
                List<EcoCbfeeitem> ecoCbfeeitems = cbfeeitemMapper.selectList(Wrappers.<EcoCbfeeitem>lambdaQuery()
                        .le(EcoCbfeeitem::getUpdateTime, endDate)//<=
                        .ge(startDate != null, EcoCbfeeitem::getUpdateTime, startDate)//>=
                        .eq(EcoCbfeeitem::getProId, project.getId())
                        .eq(EcoCbfeeitem::getDatatype,2)
                );
                for (EcoCbfeeitem ecoCbfeeitem : ecoCbfeeitems) {
                    htsr = NumberUtil.add(htsr,ecoCbfeeitem.getYstotal());
                    mbcb = NumberUtil.add(mbcb,ecoCbfeeitem.getTargetnotaxtotal());
                }
            }
            overshootSituationVo.setMbcb(mbcb);
            overshootSituationVo.setHtsr(htsr);
            mbcb_tzh = mbcb;

            BigDecimal jce = NumberUtil.subtract(htsr, mbcb_tzh).setScale(3, RoundingMode.HALF_UP);
            overshootSituationVo.setJc_jce(jce);
            BigDecimal jcl = NumberUtil.divideUseProportion(jce, htsr, 2);
            overshootSituationVo.setJc_jcl(jcl);


            overshootSituationVo.setMbcb_tzh(mbcb_tzh);
            BigDecimal yke = NumberUtil.subtract(htsr, mbcb_tzh).setScale(3, RoundingMode.HALF_UP);
            overshootSituationVo.setYk_yke(yke);
            BigDecimal ykl = NumberUtil.divideUseProportion(yke, htsr, 2);
            overshootSituationVo.setYk_ykl(ykl);
        }

        return vos;
    }

    private List<EcoCompany> findAllComPany(){
        List<EcoCompany> ecoCompanyList = ecoCompanyMapper.selectList(Wrappers.<EcoCompany>lambdaQuery()
                .eq(EcoCompany::getCompanyId, ServletUtils.getParameterToLong("paramCompId", SecurityUtils.getCompanyId()))
                .eq(EcoCompany::getStatus, "0")
                .orderByAsc(EcoCompany::getCompanySort)
        );
        for (EcoCompany ecoCompany : ecoCompanyList) {
            List<String> depIds = ecoCompanyDeptMapper.selectList(Wrappers.<EcoCompanyDept>lambdaQuery()
                    .eq(EcoCompanyDept::getCompanyId, ecoCompany.getId())
            ).stream().map(EcoCompanyDept::getDeptId).collect(Collectors.toList());
            ecoCompany.setDeptIds(depIds);
        }

        return ecoCompanyList;
    }
    private Map<String, List<LibProject>> findAllProjectOfGroupByDepId(){
        List<LibProject> libProjects = libProjectMapper.selectList(Wrappers.lambdaQuery());
        ArrayList<LibProject> newLibProjects = new ArrayList<>();
        for (LibProject libProject : libProjects) {
            if(StrUtil.isBlank(libProject.getAboutUser())) continue;
            List<PmProjectInfoBO.PmProjectInfoBO_DTL> pmProjectInfoBO_dtls = JSONUtil.toList(libProject.getAboutUser(), PmProjectInfoBO.PmProjectInfoBO_DTL.class);
            List<String> cnos = pmProjectInfoBO_dtls.stream().map(PmProjectInfoBO.PmProjectInfoBO_DTL::getCno).collect(Collectors.toList());
            if(cnos.size()==0) continue;
            List<Long> depIds = sysUserMapper.selectList(Wrappers.<SysUser>lambdaQuery().in(SysUser::getUserName, cnos)).stream().map(SysUser::getDeptId).collect(Collectors.toList());
            for (Long depId : depIds) {
                LibProject newLibproject = new LibProject();
                BeanUtil.copyProperties(libProject,newLibproject);
                newLibproject.setDeptId(depId.toString());
                newLibProjects.add(newLibproject);
            }
        }
        return newLibProjects.stream().filter(v->StrUtil.isNotBlank(v.getDeptId())).collect(Collectors.groupingBy(LibProject::getDeptId));
       // return libProjects.stream().filter(v->StrUtil.isNotBlank(v.getDeptId())).collect(Collectors.groupingBy(LibProject::getDeptId));
    }

    private List<OvershootSituationVo> assembleProjectToVo(){
        List<OvershootSituationVo> res = new ArrayList<>();
        List<EcoCompany> allComPany = this.findAllComPany();
        Map<String, List<LibProject>> projectOfGroupByDepId = this.findAllProjectOfGroupByDepId();
        for (EcoCompany ecoCompany : allComPany) {
            OvershootSituationVo overshootSituationVo = new OvershootSituationVo();
            overshootSituationVo.setId(ecoCompany.getId());
            overshootSituationVo.setName(ecoCompany.getCompanyName());
            List<String> deptIds = ecoCompany.getDeptIds();
            List<LibProject> libProjects = new ArrayList<>();
            deptIds.forEach(v -> {
                List<LibProject> projects = projectOfGroupByDepId.get(v);
                if (projects != null) libProjects.addAll(projects);
            });
            overshootSituationVo.setProjects(libProjects);
            res.add(overshootSituationVo);
        }
        return res;
    }
}
